﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
using Intellego.Web.ValidationEngine;
using MIAP.Entidades;
using MIAP.Entidades.Enums;
using MIAP.Negocio;
using MIAP.Negocio.Utiles;
using MIAPWEB.Common;

namespace MIAPWEB.Forms
{
    public partial class CargaArchivo : PageBase
    {
        #region Variables

        /// <summary>
        /// Almacena la ruta del paquete.
        /// </summary>
        private string ruta = string.Empty;

        /// <summary>
        /// Clase de negocio para perfiles
        /// </summary>
        private readonly CargaArchivosNegocio _cargaArchivosNegocio;

        /// <summary>
        /// Clase de negocio para las operaciones comunes del sistema.
        /// </summary>
        private ComunesNegocio _comunesNegocio;

        #endregion

        #region Propiedades

        /// <summary>
        /// si el archivo a cargar ha sido validado (btnVistaPreeliminar)
        /// </summary>
        private bool EsValido
        {
            get
            {
                return (bool?)this.ViewState["EsValido"] ?? false;
            }

            set
            {
                this.ViewState["EsValido"] = value;
            }
        }

        /// <summary>
        ///  Obtiene o establece la solicitud de recarga.
        /// </summary>
        public DataSet DataSourceArchivos
        {
            get
            {
                return this.ViewState["DataSourceArchivos"] as DataSet;
            }

            set
            {
                this.ViewState["DataSourceArchivos"] = value;
            }
        }

        /// <summary>
        ///  Obtiene o establece la version del archivp.
        /// </summary>
        private string ArchivoVersion
        {
            get
            {
                return this.ViewState["ArchivoVersion"] as string;
            }

            set
            {
                this.ViewState["ArchivoVersion"] = value;
            }
        }

        /// <summary>
        /// informacion del archivo seleccionado
        /// </summary>
        private ArchivoInfo ArchivoSeleccionado
        {
            get
            {
                var idArchivo = Convert.ToInt32(this.ddlArchivo.SelectedValue);
                var archivo = this._cargaArchivosNegocio.GetArchivoById(idArchivo);
                return archivo;
            }
        }

        /// <summary>
        /// stream del archivo cargado
        /// </summary>
        private byte[] _streamArchivo
        {
            get
            {
                return (byte[])this.ViewState["streamArchivo"];
            }

            set
            {
                this.ViewState["streamArchivo"] = value;
            }
        }
        /// <summary>
        /// nombre del archivo cargado
        /// </summary>
        private string _nombreArchivoCargado
        {
            get
            {
                return this.ViewState["nombreArchivoCargado"] == null ? string.Empty : this.ViewState["nombreArchivoCargado"].ToString();
            }

            set
            {
                this.ViewState["nombreArchivoCargado"] = value;
            }
        }

        /// <summary>
        /// Informacion del archivo, a cargar contiene si es carga de un archivo versionable la versin que se cargara
        /// </summary>
        private CargaArchivoInfo _cargaArchivo
        {
            get
            {
                return this.ViewState["CargaArchivoInfo"] == null ? null : (CargaArchivoInfo)this.ViewState["CargaArchivoInfo"];
            }

            set
            {
                this.ViewState["CargaArchivoInfo"] = value;
            }
        }

        public bool HasFile
        {
            get { return this._streamArchivo != null; }
        }

        public Stream FileContent
        {
            get { return StringAndStream.GenerateStreamFromBytes(this._streamArchivo); }
        }


        #endregion

        #region Constructor

        /// <summary>
        /// Constructor de la clase
        /// </summary>
        public CargaArchivo()
        {
            this._cargaArchivosNegocio = new CargaArchivosNegocio();
            this._comunesNegocio = new ComunesNegocio();
        }

        #endregion

        #region Propiedades
        #endregion

        #region Eventos
        protected void Page_Load(object sender, EventArgs e)
        {
            this.grdCargaArchivo.PageSize = Convert.ToInt32(new ConfiguracionNegocio().GetNumeroPaginasGrid().Descripcion);
            if (!IsPostBack)
            {
                this.LoadinitialCatalogs();
            }
            if (this._streamArchivo == null)
            {
                this.InitValidation();
            }

            this.CreateValidationRules();

        }

        /// <summary>
        /// Agregar las validaciones para los campos requeridos.
        /// </summary>
        private void InitValidation()
        {
            var ruleddlArchivo = new ValidationRule(this.ddlArchivo);
            ruleddlArchivo.NotEmpty(this.GetGlobalResourceObject("strings", "ErrorDropDownRequerido").ToString());
            this.ValidationEngine.Add(ruleddlArchivo);
        }

        /// <summary>
        /// Crea las reglasd e validacion
        /// </summary>
        /// <returns></returns>
        private IEnumerable<ValidationRule> CreateValidationRules()
        {
            var regreso = new List<ValidationRule>();
            var ruleTxt = new ValidationRule(this.fuArchivoCarga);

            ruleTxt.Matches(@"^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.txt|.xls|.xlsx)$",
                           this.GetGlobalResourceObject("strings", "ErrorTXT_XLS_XLSX_Permitido").ToString());

            this.ValidationEngine.Add(ruleTxt);

            regreso.Add(ruleTxt);

            return regreso;
        }

        protected void btnVistaPreliminar_Click(object sender, EventArgs e)
        {
            //ModalPopupExtender modal = (ModalPopupExtender)CurrentMasterPage.FindControl("ModalProgress");

            //modal.Show();

            //this.fuArchivoCarga.Dispose();
            this.grdCargaArchivo.DataSource = null;
            this.grdCargaArchivo.DataBind();
            this.CargaExcel(null);
            if (this.ddlArchivoRecarga.Visible && this.ddlArchivoRecarga.SelectedIndex <= 0)
            {
                this.ShowMessage(GetGlobalResourceObject("Strings", "ValidacionRecargaArchivos").ToString());
                return;
            }
            if (this.fuArchivoCarga.FileName != string.Empty)
            {
                if (this.fuArchivoCarga.FileName.Length > 50)
                {
                    this.ShowMessage(GetGlobalResourceObject("Strings", "MaxLenghtArchivo").ToString());
                    return;
                }
            }
            this.SaveArchivoSeleccionado();
            if (this._nombreArchivoCargado.Contains(".xlsx") || this._nombreArchivoCargado.Contains(".xls"))
            {
                VistaPreeliminarExcel();
            }
            if (this._nombreArchivoCargado.Contains(".txt"))
            {
                VistaPreeliminarTexto();
            }

            //modal.Hide();
        }

        private void SaveArchivoSeleccionado()
        {
            if (this.fuArchivoCarga.FileName != string.Empty)
            {
                this._streamArchivo = StringAndStream.ReadFully(this.fuArchivoCarga.FileContent);
                this._nombreArchivoCargado = this.fuArchivoCarga.FileName;
                this.lblNomrbeArchivo.Text = this._nombreArchivoCargado;
                this.fuArchivoCarga.Dispose();
            }
        }

        /// <summary>
        /// Obtiene la vista preeliminar del excel
        /// </summary>
        private void VistaPreeliminarExcel()
        {
            var archivo = ArchivoSeleccionado;

            //Validamos que el formato de archivo sea el correcto
            if (archivo.FormatoArchivo.NombreFormatoArchivo.ToLower() != Enum.GetName(typeof(FormatoArchivo), FormatoArchivo.Excel).ToLower())
            {
                this.ShowMessage(String.Format(this.GetGlobalResourceObject("strings", "ErrorCargaFormato").ToString(),
                    archivo.FormatoArchivo.NombreFormatoArchivo));
                return;
            }
            var validaExcel = new ExcelHandling(this.FileContent, this._nombreArchivoCargado, archivo.EsquemaArchivoXML);
            var dataset = validaExcel.ValidayConvierteToDataSet();
            if (dataset == null)
            {
                this.wucListaErrores.ListaErrores = validaExcel.Errores;
                this.ListaErroresPanelModalPopupExtender.Show();
                this.CargaExcel(null);
                return;
            }
            this.CargaExcel(dataset);
        }

        /// <summary>
        /// Obtiene la vista preeliminar del archivo txt
        /// </summary>
        private void VistaPreeliminarTexto()
        {
            var archivo = ArchivoSeleccionado;
            if (archivo.FormatoArchivo.NombreFormatoArchivo.ToLower() != Enum.GetName(typeof(FormatoArchivo), FormatoArchivo.Texto).ToLower())
            {
                this.ShowMessage(String.Format(this.GetGlobalResourceObject("strings", "ErrorCargaFormato").ToString(),
                    archivo.FormatoArchivo.NombreFormatoArchivo));
                return;
            }
            var archivoTexto = this._streamArchivo;
            var validaTexto = new TxtHandling(this.FileContent, archivo.EsquemaArchivoXML);
            var dataset = validaTexto.ConvertToDataSet();
            if (dataset == null)
            {
                this.wucListaErrores.ListaErrores = validaTexto.Errores;
                this.ListaErroresPanelModalPopupExtender.Show();
                EsValido = false;
            }
            this.CargaExcel(dataset);
        }

        private void CargaExcel(DataSet datos)
        {
            EsValido = datos != null;
            if (datos != null)
            {
                this.lblTotalRegistros.Text = datos.Tables[0].Rows.Count.ToString();
                this.DataSourceArchivos = datos;
                this.grdCargaArchivo.DataSource = this.DataSourceArchivos;
                this.grdCargaArchivo.DataBind();
            }
            else
            {
                this.lblTotalRegistros.Text =string.Empty;
                this.DataSourceArchivos = null;
                this.grdCargaArchivo.DataSource = this.DataSourceArchivos;
                this.grdCargaArchivo.DataBind();
                this.ArchivoVersion = string.Empty;

                this._streamArchivo = null;
                this._nombreArchivoCargado = string.Empty;
                this.lblNomrbeArchivo.Text = string.Empty;
                this.fuArchivoCarga.Dispose();
            }

        }

        protected void btnCargaInformacion_Click(object sender, EventArgs e)
        {
            if (!this.EsValido)
            {
                this.ShowMessage(GetGlobalResourceObject("Strings", "ValidacionCargaArchivo").ToString());
                return;
            }
            var archSel = ArchivoSeleccionado;
            var anio = this.ddlAño.SelectedItem.Text;
            var mes = this.ddlMes.SelectedItem.Value;
            var user = AppSessionManager.Instance.Usuario;
            var txtLinkRec = GetGlobalResourceObject("Strings", "LinkRecarga").ToString();

            //si el link dice recarga significa que el usuario quiere hacer una carga
            if (archSel.EsVersion == Enum.GetName(typeof(SiNo), SiNo.No) && LinkRecarga.Text == txtLinkRec &&
                this._cargaArchivosNegocio.ValidaArchivoCargado(archSel.Proyecto.IDProyecto, archSel.IdentificadorArchivo, Convert.ToInt32(anio), Convert.ToInt32(this.ddlMes.SelectedItem.Value)))
            {
                this.ShowMessage(GetGlobalResourceObject("Strings", "ArchivoYaCargado").ToString());
                return;
            }




            using (var prueba = new ExecutorDtsx(ArchivoSeleccionado.ProcedimientoCarga, this.ddlProyecto.SelectedItem.Text, this.ddlArchivo.SelectedItem.Text))
            {
                var variables = prueba.GetUserVariables();

                var IdCargaArchivo = this.ObtenerIdCarga();
                var version = this.ObtenerVersion();
                var valores =
                    new VariablesConocidas
                        {
                            Año = anio,
                            Mes = mes,
                            User = user,
                            Filename = this._nombreArchivoCargado,
                            Version = version
                        };
                prueba.SetValoresConocidos(valores);
                if (prueba.ExistenValoresVacios())
                {
                    wucVariablesDtsx.AdddControls(variables, prueba.ValoresYVariables);
                    VariablesModalPopupExtender.Show();
                }
                else
                {
                    CopyFiles.Instance.CopyArchivo(StringAndStream.GenerateStreamFromBytes(this._streamArchivo), this._nombreArchivoCargado, IdCargaArchivo > 0);
                    valores.IdBitacora = this.RegistraEjecucion();
                    prueba.SetValoresConocidos(valores);
                    if (!prueba.ExecuteDtsx(prueba.ValoresYVariables))
                    {
                        this.wucListaErrores.ListaErrores = prueba.Errores;
                        this.ListaErroresPanelModalPopupExtender.Show();
                        this._comunesNegocio.SetProcesoError(valores.IdBitacora, AppSessionManager.Instance.Usuario);
                        return;
                    }
                    this.ShowMessageGuardado();

                }
            }
        }

        protected void btnSalir_Click(object sender, EventArgs e)
        {
            Response.Redirect(AppUrls.Default);
        }
        #endregion

        #region Métodos

        /// <summary>
        /// Carga de los drop iniciales
        /// </summary>
        private void LoadinitialCatalogs()
        {
            this.ddlAño.DataSource = _comunesNegocio.GetAños();
            this.ddlAño.DataBind();

            this.ddlMes.DataSource = _comunesNegocio.GetMeses();
            this.ddlMes.DataBind();
            //this._comunesNegocio.SetSeleccionar(this.GetGlobalResourceObject("strings", "Seleccionar").ToString(), this.ddlMes);

            this.ddlArchivoRecarga.DataSource = this._cargaArchivosNegocio.GetArchivosAutorizados(AppSessionManager.Instance.IdUsuario);
            this.ddlArchivoRecarga.DataBind();
            this._comunesNegocio.SetSeleccionar(this.GetGlobalResourceObject("strings", "Seleccionar").ToString(), this.ddlArchivoRecarga);

            LoadProyectos();
        }

        /// <summary>
        /// carga el combo de los proyectos
        /// </summary>
        private void LoadProyectos()
        {
            this.ddlProyecto.DataSource = AppSessionManager.Instance.GetProyectosByPagina(AppUrls.CargaArchivos);
            this.ddlProyecto.DataBind();
            this.GetArchivos();
        }

        #endregion

        /// <summary>
        /// Evento de selecciond el drop de proyectos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void ddlProyecto_selectedIndexChanged(object sender, EventArgs e)
        {
            this.GetArchivos();
        }

        /// <summary>
        /// Carga los archivos dependiendo del proyecto seleccionado
        /// </summary>
        private void GetArchivos()
        {
            if (String.IsNullOrEmpty(this.ddlProyecto.SelectedValue) || Convert.ToInt32(this.ddlProyecto.SelectedValue) <= 0)
                return;
            var selectedItem = int.Parse(this.ddlProyecto.SelectedValue);
            this.ddlArchivo.DataSource = this._cargaArchivosNegocio.GetArchivosCarga(selectedItem,
                                                                                     AppSessionManager.Instance.IdUsuario);
            this.ddlArchivo.DataBind();
        }

        protected void EjecutarPaquete_btnClick(object sender, EventArgs e)
        {
            var proyecto = this.ddlProyecto.SelectedItem.Text;
            var IdCargaArchivo = this.ObtenerIdCarga();
            using (var executor = new ExecutorDtsx())
            {
                var valores = wucVariablesDtsx.GetValores();
                var idbit = this.RegistraEjecucion();
                var variables = new VariablesConocidas { IdBitacora = idbit };
                executor.SetValoresConocidos(variables);
                if (executor.ExecuteDtsx(valores))
                {
                    this.wucListaErrores.ListaErrores = executor.Errores;
                    this.ListaErroresPanelModalPopupExtender.Show();
                    this._comunesNegocio.SetProcesoError(idbit, AppSessionManager.Instance.Usuario);
                    return;
                }
                this.ShowMessageGuardado();
            }
        }

        /// <summary>
        /// registra la ejecucion de la carga o recarga en la base de datos y muestra el mensaje correspondiente
        /// </summary>
        private int RegistraEjecucion()
        {
            int idBitGral;
            var usuario = new UsuarioInfo
                {
                    AliasUsuario = AppSessionManager.Instance.Usuario,
                    IdUsuario = AppSessionManager.Instance.IdUsuario
                };
            var cargaArchivo = new CargaArchivoInfo
                {
                    Año = Convert.ToInt32(this.ddlAño.SelectedItem.Text),
                    Mes = Convert.ToInt32(this.ddlMes.SelectedItem.Value),
                    IdArchivo = Convert.ToInt32(this.ddlArchivo.SelectedValue),
                    IdProyecto = Convert.ToInt32(this.ddlProyecto.SelectedValue),
                    Version = this.ObtenerVersion(),
                    IdCargaArchivo = this.ObtenerIdCarga(),
                    NombreArchivoSubir = this._nombreArchivoCargado
                };
            idBitGral = cargaArchivo.IdCargaArchivo == 0 ? this._cargaArchivosNegocio.CargaArchivo(cargaArchivo, usuario) : this._cargaArchivosNegocio.RecargaArchivo(cargaArchivo, usuario);

            return idBitGral;
        }

        private void ShowMessageGuardado()
        {
            string mensaje;
            var idArchivo = this.ObtenerIdCarga();
            var version = this.ObtenerVersion();
            if (idArchivo == 0)
            {
                mensaje = string.IsNullOrEmpty(version)
                                  ? this.GetGlobalResourceObject("strings", "CargaArchivo").ToString()
                                  : string.Format(
                                      this.GetGlobalResourceObject("strings", "CargaArchivoVersion").ToString(),
                                      version);
            }
            else
            {
                mensaje = string.IsNullOrEmpty(version)
                   ? this.GetGlobalResourceObject("strings", "RecargaArchivo").ToString()
                   : string.Format(
                       this.GetGlobalResourceObject("strings", "RecargaArchivoVersion").ToString(),
                       version);
            }
            this.ShowMessage(mensaje, this.PreviousPage);
        }

        /// <summary>
        /// Cambia el estatus de carga o recarga del archivo
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void LinkRecarga_onClick(object sender, EventArgs e)
        {
            var recarga = GetGlobalResourceObject("Strings", "LinkRecarga").ToString();
            var carga = GetGlobalResourceObject("Strings", "LinkCarga").ToString();
            if (this.LinkRecarga.Text == recarga)
            {
                divRecarga.Visible = true;
                //lo cambiamos por carga
                this.LinkRecarga.Text = carga;
                this.SetEnableDrops(false);
                this.lblTituloPagina.Text = GetGlobalResourceObject("Strings", "TituloRecargaArchivos").ToString();
            }
            else if (this.LinkRecarga.Text == carga)
            {
                divRecarga.Visible = false;
                this.SetEnableDrops(true);
                this.LinkRecarga.Text = recarga;
                this.lblTituloPagina.Text = GetGlobalResourceObject("Strings", "TituloCargaArchivos").ToString();
            }
        }

        /// <summary>
        /// Habilita o deshabilita los controles de lista para asi indicar que sera una recarga o carga del archivo
        /// </summary>
        /// <param name="enable">true si seran habilitados, false en caso contrario</param>
        private void SetEnableDrops(bool enable)
        {
            this.Clean();
            this.ddlProyecto.Enabled = enable;
            this.ddlArchivo.Enabled = enable;
            this.ddlAño.Enabled = enable;
            this.ddlMes.Enabled = enable;
        }

        /// <summary>
        /// limpiamos la seleccion de la pantalla y se recargan los combos necesarios
        /// </summary>
        private void Clean()
        {
            this.CargaExcel(null);
            this.fuArchivoCarga.Dispose();
            this._nombreArchivoCargado = null;
            this._streamArchivo = null;
            this.ddlProyecto.ClearSelection();
            this.ddlArchivo.ClearSelection();
            this.ddlAño.ClearSelection();
            this.ddlMes.ClearSelection();
            this.LoadProyectos();
        }

        protected void DdlArchivoRecarga_onClick(object sender, EventArgs e)
        {
            var archRecar = this.ddlArchivoRecarga.SelectedItem.Text;
            var version = archRecar.Contains("--") ? archRecar.Split(new[] { "--" }, StringSplitOptions.None)[1].Trim() : string.Empty;
            var infoArchivo =
                this._cargaArchivosNegocio.GetArchivoCarga(Convert.ToInt32(this.ddlArchivoRecarga.SelectedValue),
                                                           version);
            this.ddlAño.SelectedValue = infoArchivo.Año.ToString();
            this.ddlMes.SelectedValue = infoArchivo.Mes.ToString();
            var itemArchivo = new ArchivoInfo
                {
                    IdentificadorArchivo = infoArchivo.IdArchivo.Value,
                    NombreArchivo = infoArchivo.NombreArchivo
                };
            var itemProyecto = new ProyectoInfo()
            {
                IDProyecto = infoArchivo.IdProyecto.Value,
                NombreProyecto = infoArchivo.NombreProyecto
            };
            this._comunesNegocio.SelectProyectoItem(this.ddlProyecto, itemProyecto);
            this.GetArchivos();
            this._comunesNegocio.SelectArchivoItem(this.ddlArchivo, itemArchivo);

        }

        /// <summary>
        /// obtenemos la version a cargar o recargar del archivo 
        /// </summary>
        /// <returns></returns>
        private string ObtenerVersion()
        {
            if (String.IsNullOrEmpty(this.ArchivoVersion))
            {
                var archivo = ArchivoSeleccionado;
                var txtLinkRec = GetGlobalResourceObject("Strings", "LinkRecarga").ToString();
                //si el link dice recarga significa que el usuario quiere hacer una carga
                if (LinkRecarga.Text == txtLinkRec)
                {
                    var versionSiguiente = string.Empty;
                    if (archivo.EsVersion == Enum.GetName(typeof(SiNo), SiNo.Si))
                    {
                        var año = Convert.ToInt32(this.ddlAño.SelectedItem.Text);
                        var mes = this.ddlMes.SelectedValue == "-1"
                                      ? (int?)null
                                      : Convert.ToInt32(ddlMes.SelectedValue);
                        versionSiguiente = this._cargaArchivosNegocio.GetVersionCargar(archivo.IdentificadorArchivo, año,
                                                                                       mes);
                    }
                    this.ArchivoVersion = versionSiguiente;
                }
                else
                {
                    var archRecar = this.ddlArchivoRecarga.SelectedItem.Text;
                    this.ArchivoVersion = archRecar.Contains("--")
                                              ? archRecar.Split(new[] { "--" }, StringSplitOptions.None)[1].Trim()
                                              : string.Empty;
                }
            }
            return this.ArchivoVersion;
        }

        /// <summary>
        /// obtenemos el id de carga o recarga 
        /// </summary>
        /// <returns></returns>
        private int ObtenerIdCarga()
        {
            var txtLinkRec = GetGlobalResourceObject("Strings", "LinkRecarga").ToString();
            //si el link dice recarga significa que el usuario quiere hacer una carga
            if (LinkRecarga.Text == txtLinkRec)
            {
                return 0;
            }
            var archRecar = this.ddlArchivoRecarga.SelectedItem.Text;
            var idArch = Convert.ToInt32(this.ddlArchivoRecarga.SelectedValue);
            var version = archRecar.Contains("--") ? archRecar.Split(new[] { "--" }, StringSplitOptions.None)[1].Trim() : string.Empty;

            return this._cargaArchivosNegocio.GetArchivoCarga(idArch, version).IdCargaArchivo;

        }

        protected void fuArchivoCarga_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
        {
            this.lblNomrbeArchivo.Text = this.fuArchivoCarga.FileName;
        }

        protected void grdCargaArchivo_OnPageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            this.grdCargaArchivo.PageIndex = e.NewPageIndex;
            this.grdCargaArchivo.DataSource = this.DataSourceArchivos;
            this.grdCargaArchivo.DataBind();
        }
    }
}